// com.zhu.rtda.OperandStack.java
package com.zhu.rtda;

/**
 * 操作数栈
 * 使用 Slot 数组实现，通过 size 指针管理栈顶
 * 参考《自己动手写Java虚拟机》第4章
 */
public class OperandStack {
    // size 指向的是 下一个可写入的位置，也就是栈顶的“上方”
    // 它是数组中元素的个数,但是它不是栈顶元素的下标
    private int size;
    private Slot[] slots;    // 底层存储
    private int maxStack;    // 缓存最大深度，用于检查

    /**
     * 创建指定最大深度的操作数栈
     * @param maxStack 操作数栈的最大深度
     */
    public OperandStack(int maxStack) {
        if (maxStack <= 0) {
            throw new IllegalArgumentException("maxStack must > 0!");
        }
        this.maxStack = maxStack;
        this.slots = new Slot[maxStack];
        this.size = 0;
        // 初始化所有 Slot
        for (int i = 0; i < maxStack; i++) {
            slots[i] = new Slot();
        }
    }

    // --- 推入 int ---
    public void pushInt(int val) {
        if (size >= maxStack) {
            throw new RuntimeException("Operand stack overflow!");
        }
        slots[size].setNum(val);
        size++;
    }

    public int popInt() {
        if (size <= 0) {
            throw new RuntimeException("Operand stack underflow!");
        }
        size--;
        return slots[size].getNum();
    }

    // --- 推入 float ---
    public void pushFloat(float val) {
        if (size >= maxStack) {
            throw new RuntimeException("Operand stack overflow!");
        }
        int bits = Float.floatToIntBits(val);
        slots[size].setNum(bits);
        size++;
    }

    public float popFloat() {
        if (size <= 0) {
            throw new RuntimeException("Operand stack underflow!");
        }
        size--;
        int bits = slots[size].getNum();
        return Float.intBitsToFloat(bits);
    }

    // --- 推入 long ---
    public void pushLong(long val) {
        if (size + 2 > maxStack) {
            throw new RuntimeException("Operand stack overflow!");
        }
        slots[size].setNum((int) (val >> 32));     // 高32位
        slots[size + 1].setNum((int) val);         // 低32位
        size += 2;
    }

    public long popLong() {
        if (size < 2) {
            throw new RuntimeException("Operand stack underflow!");
        }
        size -= 2;
        long high = ((long) slots[size].getNum()) << 32;
        long low = (long) slots[size + 1].getNum();
        return high | low;
    }

    // --- 推入 double ---
    public void pushDouble(double val) {
        long bits = Double.doubleToLongBits(val);
        pushLong(bits); // 复用 pushLong 的溢出检查
    }

    public double popDouble() {
        long bits = popLong(); // 复用 popLong 的下溢检查
        return Double.longBitsToDouble(bits);
    }

    // --- 推入引用 ---
    public void pushRef(InstanceOop ref) {
        if (size >= maxStack) {
            throw new RuntimeException("Operand stack overflow!");
        }
        slots[size].setRef(ref);
        size++;
    }

    public InstanceOop popRef() {
        if (size <= 0) {
            throw new RuntimeException("Operand stack underflow!");
        }
        size--;
        return slots[size].getRef();
    }

    // --- 推入 Slot（保留原名，仅加检查）---
    public void pushSlot(Slot slot) {
        if (size >= maxStack) {
            throw new RuntimeException("Operand stack overflow!");
        }
        slots[size] = slot;
        size++;
    }

    // --- 弹出 Slot（保留原名，仅加检查）---
    public Slot popSlot() {
        if (size <= 0) {
            throw new RuntimeException("Operand stack underflow!");
        }
        size--;
        return slots[size];
    }

    // --- 获取当前栈大小 ---
    public int size() {
        return size;
    }

    // --- 判空 ---
    public boolean isEmpty() {
        return size == 0;
    }

    // --- 获取底层数组（用于调试）---
    public Slot[] getSlots() {
        return slots;
    }
}